/*
The fat32.h header file defines constants and prototypes for the FAT-32 File System management functions
*/

#ifndef _VFS_FAT32_H
#define _VFS_FAT32_H

/* from lib files */
#include <types.h>

/* File attributes (00ARSHDV) */

#define FAT32_FA_ARCHIVE    0x20
#define FAT32_FA_RDONLY     0x10
#define FAT32_FA_SYSTEM     0x08
#define FAT32_FA_HIDDEN     0x04
#define FAT32_FA_DIRECTORY  0x02
#define FAT32_FA_VOLUME     0x01

// Long File Name first entry: rdonly | system | hidden | volume
#define FAT32_FA_LFN        0x1D
// Long File Name sub-component: archive | rdonly | system | hidden | directory | volume
#define FAT32_FA_LFN_MASK   0x3F


// end of cluster chain in FAT structure
#define FAT32_EOC   0x0FFFFFFF
// bad cluster marker in FAT structure
#define FAT32_BAD   0x0FFFFFF7
// free cluster marker in FAT structure
#define FAT32_FREE  0x00000000

#pragma pack(1)

struct FAT32_Boot_Record {
  byte_t BS_jmpBoot[3];
  byte_t BS_OEM_Name[8];
  word_t BPB_BytesPerSec;
  byte_t BPB_SecPerClus;
  word_t BPB_ResSecCount;
  byte_t BPB_NumFATs;
  word_t BPB_RootEntCount;     /* N/A for FAT-32 */
  word_t BPB_TotSec16;         /* N/A for FAT-32 */
  byte_t BPB_Media;            /* 0xF8 for Hard Disks */
  word_t BPB_FATSz16;          /* zero for FAT-32 */
  word_t BPB_SecPerTrack;
  word_t BPB_NumHeads;
  dword_t BPB_HiddenSec;
  dword_t BPB_TotSec32;
  dword_t BPB_FATSz32;
  word_t BPB_ExtFlags;  
  word_t BPB_FSVersion;
  dword_t BPB_RootClus;        /* start of root directory */
  word_t BPB_FSInfo;           /* start of FS Info structure */
  word_t BPB_BkBootSec;
  byte_t BPB_Reserved[12];
  byte_t BS_DriveNum;
  byte_t BS_Reserved1;         /* can be high byte of previous entry */
  byte_t BS_BootSignature;
  dword_t BS_VolumeID;
  byte_t BS_VolumeLabel[11];
  byte_t BS_FSType[8];
  byte_t executable_code[420];
  byte_t boot_signature[2];    /* 0x55,0xAA */
};

struct FAT32_directory_entry {
  byte_t name[8];
  byte_t extension[3];
  byte_t attributes;
  byte_t reserved_nt;        /* reserved for Windows NT, always 0 */
  byte_t creation_time_ms;   /* millisecond portion */
  word_t creation_time_hm;   /* hour and minute */
  word_t creation_date;
  word_t last_access_date;
  word_t cluster_high;
  word_t time;
  word_t date;
  word_t cluster_low;
  dword_t size;
};

struct FAT32_LFN_entry {
  byte_t ordinal;
  word_t uc_1;
  word_t uc_2;
  word_t uc_3;
  word_t uc_4;
  word_t uc_5;
  byte_t attributes;
  byte_t type;        /* reserved, always zero */
  byte_t checksum; 
  word_t uc_6;
  word_t uc_7;
  word_t uc_8;
  word_t uc_9;
  word_t uc_10;
  word_t uc_11;  
  word_t cluster;     /* unused, always zero */
  word_t uc_12;  
  word_t uc_13;  
};

#pragma pack(4)

// custom structure for VFS driver
struct VFS_FAT32_Custom {
  struct FAT32_Boot_Record *FAT32_BR;
  int RootDirSectors;
  int FATSz;
  int FirstDataSector;
  int sectors_per_cluster;
};

/* Functions prototypes */
extern int vfs_fat32_initialize();
extern int vfs_fat32_volume(struct vfs_partition_info *part_info);
extern int vfs_fat32_diagnostics(void);

#endif /* _VFS_FAT32_H */
